
#ifndef __IMAGE_STUFF_H__
#define __IMAGE_STUFF_H__

// == External Modules ======

#ifdef _WIN32
#include <Windows.h>
#include <GL/glut.h>
#elif defined (__APPLE__)
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

#include <stdlib.h>
#include <deque>

// =========================================================
// Image Utilities
// =========================================================

// Static non-animated image
struct static_image_t
{
	unsigned int width;
	unsigned int height;
	unsigned int channels;
	unsigned int buffsiz;
	void * pixels;
};

// Loads 24bit And 32bit .bmp Images.
static_image_t * LoadImageFromFile(const char * fileName);

// Free The Allocated Memory.
void FreeImage(static_image_t ** ppImage);

// Creates An Scaled Version Of The Image Passed In.
static_image_t * ScaleImage(const static_image_t * pImageIn, int newWidth, int newHeight);

// This Function Expects The Proper GL States To Be Set, Such As An Ortho 2D Projection, Color Enabled, Etc...
void DrawImage(int x, int y, const static_image_t * pImage);

// =========================================================
// Sprite2D Class
// =========================================================

class Sprite2D
{
public:

	Sprite2D(bool free_images_on_death = true);

	void PushFrame(const static_image_t * pImage, float delay);

	void Draw(int x, int y, unsigned int firstFrame, unsigned int lastFrame);

	void Draw(int x, int y);

	static void UpdateAnimationTimer(void);

	const static_image_t * GetFrame(unsigned int frame) const;

	unsigned int CurrentFrame(void) const;

	unsigned int NumFrames(void) const;

	void SetPerFrameDelay(float delay);

	void FreeImagePointers(void);

	~Sprite2D(void);

protected:

	struct frame_t
	{
	public:

		frame_t(void)
			: image_pointer(0), delay(0.0f)
			{
			}

		frame_t(const frame_t & r)
			: image_pointer(r.image_pointer), delay(r.delay)
			{
			}

		frame_t(const static_image_t * pImage, float delay)
			: image_pointer(pImage), delay(delay)
			{
			}

		frame_t & operator = (const frame_t & r)
			{
			image_pointer = r.image_pointer;
			delay = r.delay;
			return (*this);
			}

		~frame_t(void)
			{
			}

		const static_image_t * image_pointer;
		float delay;
	};

private:

	static float m_elapsed_time;
	static double m_time[2];

	typedef std::deque<frame_t> frame_deque;
	frame_deque m_image_frames;

	const bool kill_ptrs;
	unsigned int m_current_frame;
	float m_time_count;
};

// =========================================================
// glPrintf (For Simple Text Drawing)
// =========================================================

// Works Like The Regular 'printf' C Function.
int glPrintf(int x, int y, const char * format, ...);

// =========================================================
// Button2D Class
// =========================================================

class Button2D
{
public:

	Button2D(void);

	Button2D(static_image_t *_image, int _x, int _y);

	void SetImage(static_image_t *_image, int _x, int _y);

	static_image_t * returnImage(void) const;

	void FreeMemory(void);

	void DrawButton(void) const;

	bool testColision(int _x, int _y) const;

	inline int getX(void) const { return (x); };

	inline int getY(void) const { return (y); };

	~Button2D(void);

private:

	static_image_t * image;
	int x, y;
};

#endif // __IMAGE_STUFF_H__
